package com.ly.mssp.license.client.registry;

import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.ly.mssp.license.client.http.HttpClient;

import okhttp3.Response;

/**
 * 
 * 操作镜像的manifest信息
 * 
 * @author Administrator
 *
 */
public class ManifestClient {
	
	private HttpClient client;
	
	private String baseUrl;
	
	public static String MediaTypeManifest_V1="application/vnd.docker.distribution.manifest.v1+json";
	
	public static String MediaTypeManifest_V2="application/vnd.docker.distribution.manifest.v2+json";
	
	private String userName;
	
	private String password;
	
	public ManifestClient(String address, int port, String userName, String password) {
		this.baseUrl="http://"+address+":"+port+"/v2/";
		this.client=new HttpClient();
		this.userName=userName;
		this.password=password;
	}
	
	/**
	 * 
	 * 获取镜像的manifest信息
	 * 
	 * @param imageName
	 * @param tagName
	 * @return
	 */
	public String getManifest(String imageName, String tagName) {
		
		String url=baseUrl+imageName+"/manifests/"+tagName;
		
		Map<String, String> headers=new HashMap();
		
		headers.put("Accept", MediaTypeManifest_V1);
	
		try {
			Response resp=client.get(url, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				
				if (token!=null) {
					
					Map<String, String> headers2=new HashMap();
					headers2.put("Authorization", "Bearer " + token);
					
					resp = client.get(url, headers2);
				}else {
					return null;
				}
			}			
			
			if (resp.code()==200) {				
				return resp.body().string();				
			}else {
				return null;
			}			
		}catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 
	 * 获取镜像的manifest v2 信息
	 * 
	 * @param imageName
	 * @param tagName
	 * @return
	 */
	public String getManifest2(String imageName, String tagName) {
		String url=baseUrl+imageName+"/manifests/"+tagName;
		
		Map<String, String> headers=new HashMap();
		
		headers.put("Accept", MediaTypeManifest_V2);
	
		try {
			Response resp=client.head(url, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				if (token!=null) {
					Map<String, String> headers2=new HashMap();
					headers2.put("Authorization", "Bearer " + token);
					headers2.put("Accept", MediaTypeManifest_V2);
					
					resp = client.head(url, headers2);
				}else {
					return null;
				}
				
			}
			
			if (resp.code()==200) {				
				resp=client.get(url, headers);
				if (resp.code()==200) {
					return resp.body().string();
				}else {
					return null;
				}
			}else {
				return null;
			}			
		}catch(Exception e) {
			return null;
		}
	}
	
	/**
	 * 
	 *  获取镜像的digest
	 * 
	 * @param imageName
	 * @param tagName
	 * @return
	 */
	public String getDigest(String imageName, String tagName) {
		
		String url=baseUrl+imageName+"/manifests/"+tagName;
		
		Map<String, String> headers=new HashMap();
			
		try {
			Response resp=client.head(url, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				if (token!=null) {
					
					Map<String, String> headers2=new HashMap();
					headers2.put("Authorization", "Bearer " + token);
					
					resp = client.get(url, headers2);
				}else {
					return null;
				}
				
			}
			
			if (resp.code()==200) {
				return resp.header("Docker-Content-Digest");
			}else {
				return null;
			}
		}catch(Exception e) {
			return null;
		}
	}
	
	/**
	 * 
	 *  删除镜像的manifest信息
	 * 
	 * @param imageName
	 * @param digest
	 * @return
	 */
	public boolean deleteManifest(String imageName, String digest) {
		
		String url=baseUrl+imageName+"/manifests/"+digest;
		
		Map<String, String> headers=new HashMap();
			
		try {
			Response resp=client.delete(url, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				if (token!=null) {
					
					Map<String, String> headers2=new HashMap();
					headers2.put("Authorization", "Bearer " + token);
					
					resp = client.get(url, headers2);
				}else {
					return false;
				}
				
			}
			
			return resp.code()==200;
		}catch(Exception e) {
			return false;
		}		
	}
	
	/**
	 * 
	 * 更新镜像的manifest信息
	 * 
	 * @param imageName
	 * @param tagName
	 * @param manifest
	 * @return
	 */
	public boolean setManifest(String imageName, String tagName, String manifest) {
		String url=baseUrl+imageName+"/manifests/"+tagName;
				
		try {
			
			Map<String, String> headers=new HashMap<String, String>();
			//headers.put("content-type", MediaTypeManifest_V1);
			
			Response resp=client.setManifests(url, manifest, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				if (token!=null) {
					
					Map<String, String> headers2=new HashMap();
					headers2.put("Authorization", "Bearer " + token);
					
					resp = client.get(url, headers2);
				}else {
					return false;
				}
				
			}
			
			if (resp.code()==200) {
				return true;
			}else {
				String val=resp.body().string();
				System.out.println(val);
				return false;
			}
		}catch(Exception e) {
			return false;
		}
	}
	
	public String getConfig(String imageName, String digest) {
		String url=baseUrl+imageName+"/blobs/"+digest;
		
		Map<String, String> headers=new HashMap();
			
		try {
			Response resp=client.get(url, headers);
			
			if (resp.code()==401) {
				
				String token=getDockerToken(resp);
				if (token!=null) {					
					headers.put("Authorization", "Bearer " + token);
					
					resp = client.get(url, headers);
				}else {
					return null;
				}
				
			}
			
			if (resp.code()==200) {
				return resp.body().string();
			}else {
				return null;
			}
		}catch(Exception e) {
			return null;
		}
	}
	
	private String getDockerToken(Response response) {
		//String token_url=url+"?account=" + userName + "&client_id=docker&service=" + service + "&scope=" + scope;
		try {
			String authenticate=response.header("Www-Authenticate");
			if (authenticate!=null) {
				String[] items=authenticate.split(",");
				String url=null;
				String service=null;
				String scope=null;
				for (int i=0;i<items.length;i++) {
					String val=items[i];
					if (val.startsWith("Bearer realm=")) {
						url=val.substring(14, val.length()-1);
					}else if (val.startsWith("service=")) {
						service=val.substring(9, val.length()-1);
					}else if (val.startsWith("scope=")) {
						scope=val.substring(7, val.length()-1);
					}
				}	
				
				url=url+"?account="+userName+"&client_id=docker&service="+service+"&scope=" + scope;

				
				Map<String, String> headers=new HashMap();
				String token=userName+":"+password;
				byte[] tmp=Base64.getEncoder().encode(token.getBytes());
				token=new String(tmp);
				headers.put("Authorization", "Basic " + token);
				
				Response resp=this.client.get(url, headers);
				if (resp.code()==200) {
					JSONObject o=JSONObject.parseObject(resp.body().string());
					return o.getString("token");
				}else {
					return null;
				}
				
			}else {
				return null;
			}
		}catch(Exception e) {
			return null;
		}
	}
	
	
	private byte[] payload(String content) {
		return null;
	}
	
	@Override
	public void finalize() throws Throwable{
		try {
			this.client.close();
		}catch(Exception e) {
			
		}
		super.finalize();
	}
}
